home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume13 / make1.6 / part02 < prev    next >
Encoding:
Text File  |  1990-06-02  |  49.6 KB  |  2,273 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v13i019: PD make V1.6 (Part 2 of 2)
  3. From: greggy@zebra.UUCP (Greg Yachuk)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 19
  7. Submitted-by: greggy@zebra.UUCP (Greg Yachuk)
  8. Archive-name: make1.6/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # If this archive is complete, you will see the following message at the end:
  17. #        "End of archive 2 (of 2)."
  18. # Contents:  build.c default.mk default.msc make.h makefile
  19. #   makefile.msc parse.c tstring.c tstring.h
  20. # Wrapped by greggy@etude on Thu May 31 10:55:31 1990
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'build.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'build.c'\"
  24. else
  25. echo shar: Extracting \"'build.c'\" \(7577 characters\)
  26. sed "s/^X//" >'build.c' <<'END_OF_FILE'
  27. X/*
  28. X * build.c    An imitation of the Unix MAKE facility
  29. X *
  30. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  31. X * 88-10-06 v1.1    changed prerequisite list handling
  32. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  33. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  34. X * 89-08-01 v1.4 AB    lots of new options and code
  35. X * 89-10-30 v1.5    -f -S -q options, took some changes from v1.4
  36. X * 90-04-18 v1.6    -b -- -W options, emulate <<, non-BSD cleanup
  37. X */
  38. X
  39. X#include <stdio.h>
  40. X#include <string.h>
  41. X#ifdef    MSDOS
  42. X#include <stdlib.h>
  43. X#include <process.h>
  44. X#endif
  45. X#ifdef    BSD
  46. X#include <sys/wait.h>
  47. X#endif
  48. X
  49. X#include "make.h"
  50. X#include "tstring.h"
  51. X#include "decl.h"
  52. X
  53. X#ifndef    MSDOS
  54. Xchar  **bsearch();
  55. X#endif
  56. X
  57. Xchar   *tmpfn = NULL;
  58. X#define    shellunlink()    if(tmpfn!=NULL)unlink(tmpfn),tfree(tmpfn),tmpfn=NULL
  59. X
  60. X/*
  61. X * shell_cmpr    - comparison routine for "shell command" binary search.
  62. X */
  63. Xshell_cmpr(key, list)
  64. Xchar   *key;
  65. Xchar  **list;
  66. X{
  67. X    return (strcmp(key, *list));
  68. X}
  69. X
  70. X/*
  71. X * build    - process the shell commands
  72. X */
  73. Xbuild(shellp)
  74. Xshellptr *shellp;
  75. X{
  76. X    char  **argv;        /* argified version of scmd */
  77. X    int     runst;        /* exec return status */
  78. X    char   *scmd;        /* command with symbols broken out */
  79. X    char   *tcmd;        /* copy of scmd for `tokenize' */
  80. X    char   *errnum;        /* error number in ascii */
  81. X    char   *errmsg;        /* error message */
  82. X    int     i;
  83. X    char   *sp;
  84. X    char   *tp;
  85. X    char  **shcp;        /* pointer to shell command list */
  86. X
  87. X    if (shellp == NULL || opts.query)
  88. X        return (0);
  89. X
  90. X    /* process every shell line */
  91. X
  92. X    for (; *shellp != NULL;
  93. X         tfree(scmd), tfree(tcmd), tfree(argv), ++shellp)
  94. X    {
  95. X        /* breakout runtime symbols (e.g. $* $@ $<) */
  96. X        scmd = breakout((*shellp)->scmd);
  97. X
  98. X        /* make a copy because tokenize litters '\0's */
  99. X        tcmd = tstrcpy(scmd);
  100. X        argv = tokenize(tcmd);
  101. X
  102. X        for (tp = scmd, i = 0; argv[i]; i++)
  103. X        {
  104. X            /* pretend to handle inline input ("<<" operator) */
  105. X            while ((sp = strchr(argv[i], '<')) != NULL)
  106. X            {
  107. X                if (*++sp != '<')
  108. X                    continue;
  109. X
  110. X                sp[-1] = '\0';
  111. X
  112. X                /* got "<<".  collect commands into a file */
  113. X                if (*++sp != '\0')    /* got "<<TAG" */
  114. X                    sp = shellinput(&shellp, sp);
  115. X                else
  116. X                {
  117. X                    /* got "<< TAG" (note space before TAG) */
  118. X                    sp = shellinput(&shellp, argv[i + 1]);
  119. X                    if (argv[i + 1])
  120. X                    {
  121. X                        tfree(argv[i + 1]);
  122. X                        argv[i + 1] = tstrcpy("");
  123. X                    }
  124. X                }
  125. X
  126. X                /* add the filename to the argument */
  127. X                sp = tstrcat(argv[i], sp);
  128. X                tfree(argv[i]);
  129. X                argv[i] = sp;
  130. X            }
  131. X
  132. X            /* now strip the quotes from the argument */
  133. X            strcpy(tp, tunquote(argv[i]));
  134. X            while (*tp++);
  135. X            tp[-1] = ' ';
  136. X        }
  137. X
  138. X        /* finally, terminate the command line (scmd) */
  139. X        tp[-1] = '\0';
  140. X
  141. X        if (!opts.silent && (opts.noexec || !(*shellp)->s_silent))
  142. X        {
  143. X            puts(scmd);
  144. X            fflush(stdout);
  145. X        }
  146. X
  147. X        /* look for $(MAKE) */
  148. X        if (equal(argv[0], opts.make))
  149. X        {
  150. X            /* call ourselves recursively */
  151. X            new_make(argv);
  152. X            continue;
  153. X        }
  154. X
  155. X        if (opts.noexec)
  156. X            continue;
  157. X
  158. X        /* any SHELL meta-characters MUST be handled by the shell */
  159. X        if (!(*shellp)->s_shell && strpbrk(scmd, SHELL_METAS))
  160. X            (*shellp)->s_shell = 1;
  161. X
  162. X        if (shell_cmds && !(*shellp)->s_shell)
  163. X        {
  164. X            /* check for COMMAND.COM builtin commands */
  165. X            for (shcp = shell_cmds; *shcp; ++shcp);
  166. X            shcp = bsearch(argv[0], shell_cmds,
  167. X                       shcp - shell_cmds - 1,
  168. X                       sizeof(char *), shell_cmpr);
  169. X            (*shellp)->s_shell = (shcp != NULL);
  170. X        }
  171. X
  172. X        /* run without COMMAND.COM if possible, 'cause it uses RAM */
  173. X        if (!(*shellp)->s_shell)
  174. X            runst = spawnvp(P_WAIT, argv[0], argv);
  175. X        else
  176. X            runst = system(scmd);
  177. X
  178. X        shellunlink();
  179. X
  180. X        if (runst == 0)
  181. X            continue;
  182. X
  183. X        /* uh-oh, an error */
  184. X        if (runst == -1)
  185. X            perror("make");
  186. X
  187. X        errnum = talloc(18);
  188. X#ifdef    MSDOS
  189. X        errnum = itoa(runst, errnum, 10);
  190. X#else
  191. X        sprintf(errnum, "%d", runst);
  192. X#endif
  193. X        errmsg = (opts.keepon) ? "\007*** Ignoring Error code "
  194. X            : "\007*** Error code ";
  195. X        errmsg = tstrcat(errmsg, errnum);
  196. X        terror(0, errmsg);
  197. X        tfree(errmsg);
  198. X        tfree(errnum);
  199. X
  200. X        if (opts.keepon)
  201. X            return (1);
  202. X
  203. X        if (!opts.ignore && !(*shellp)->s_ignore)
  204. X            exit(1);
  205. X    }
  206. X
  207. X    return (0);
  208. X}
  209. X
  210. X
  211. X/*
  212. X * shellinput    - write the list of commands into a temp file, and return name
  213. X */
  214. Xchar   *shellinput(shellp, eof)
  215. Xshellptr **shellp;
  216. Xchar   *eof;
  217. X{
  218. X    int     eoflen;
  219. X    char   *scmd;
  220. X    FILE   *tfp;
  221. X
  222. X    /* get rid of obvious errors */
  223. X    if (shellp == NULL || *shellp == NULL)
  224. X        return (NULL);
  225. X
  226. X    eoflen = (eof) ? strlen(eof) : 0;
  227. X
  228. X    /* find the name of a candidate temporary file */
  229. X    tmpfn = tempnam(NULL, "mk");
  230. X
  231. X    /* write contents to stdout when '-n' is specified */
  232. X    if (opts.noexec && !opts.silent && !(**shellp)->s_silent)
  233. X        tfp = stdout;
  234. X    else
  235. X        tfp = fopen(tmpfn, "w");
  236. X
  237. X    while (*++*shellp)
  238. X    {
  239. X        /* break out the current shell command */
  240. X        scmd = breakout((**shellp)->scmd);
  241. X
  242. X        /* propogate the shell command attributes */
  243. X        (**shellp)->s_silent = ((*shellp)[-1])->s_silent;
  244. X        (**shellp)->s_ignore = ((*shellp)[-1])->s_ignore;
  245. X        (**shellp)->s_shell = ((*shellp)[-1])->s_shell;
  246. X
  247. X        /* see if we've reached the eof-word */
  248. X        if (eof && !strncmp(scmd, eof, eoflen))
  249. X            break;
  250. X
  251. X        /* no there, so write out the command to the temp file */
  252. X        if (tfp)
  253. X        {
  254. X            fputs(scmd, tfp);
  255. X            fputc('\n', tfp);
  256. X        }
  257. X
  258. X        /* free the string allocated by breakout() */
  259. X        tfree(scmd);
  260. X    }
  261. X
  262. X    if (tfp != stdout)
  263. X        fclose(tfp);
  264. X
  265. X    if (**shellp == NULL)
  266. X        --* shellp;    /* point at last shell command */
  267. X    else
  268. X        tfree(scmd);    /* free EOF-word */
  269. X
  270. X    return (tmpfn);
  271. X}
  272. X
  273. X
  274. X/*
  275. X * new_make    - save current environment
  276. X *        - call make() recursively (actually main())
  277. X *        - clean up new environment
  278. X *        - restore environment
  279. X */
  280. Xnew_make(argv)
  281. Xchar  **argv;
  282. X{
  283. X    targptr thead, tnext, tsuffix;
  284. X    fileptr fhead, fnext;
  285. X    symptr  shead, snext;
  286. X    shellptr shhead, shnext;
  287. X    char  **shcmds;
  288. X    char  **ttlist;
  289. X    long    tnow;
  290. X    optnode topts;
  291. X    int     i;
  292. X
  293. X    /* save all the globals */
  294. X    tsuffix = suffix_targ;
  295. X    thead = target_list;
  296. X    fhead = file_list;
  297. X    shead = symbol_list;
  298. X    shhead = shell_list;
  299. X    shcmds = shell_cmds;
  300. X    ttlist = tlist;
  301. X    tnow = now;
  302. X    topts = opts;
  303. X
  304. X    /* count the arguments */
  305. X    for (i = 0; argv[i]; ++i)
  306. X        tunquote(argv[i]);
  307. X
  308. X    /* call ourselves recursively; this inherits flags */
  309. X    ++make_level;
  310. X    main(i, argv);
  311. X    --make_level;
  312. X
  313. X    /* we're back, so gotta clean up and dispose of a few things */
  314. X    while (target_list)
  315. X    {
  316. X        tnext = target_list->tnext;
  317. X        if (target_list->tpreq)
  318. X            tfree(target_list->tpreq);
  319. X        if (target_list->tshell)
  320. X            tfree(target_list->tshell);
  321. X        tfree(target_list);
  322. X        target_list = tnext;
  323. X    }
  324. X
  325. X    while (file_list)
  326. X    {
  327. X        fnext = file_list->fnext;
  328. X        tfree(file_list->fname);
  329. X        tfree(file_list);
  330. X        file_list = fnext;
  331. X    }
  332. X
  333. X    /* don't drop all symbols, just the new ones */
  334. X
  335. X    while (symbol_list != shead)
  336. X    {
  337. X        snext = symbol_list->snext;
  338. X        tfree(symbol_list->sname);
  339. X        tfree(symbol_list->svalue);
  340. X        tfree(symbol_list);
  341. X        symbol_list = snext;
  342. X    }
  343. X
  344. X    while (shell_list)
  345. X    {
  346. X        shnext = shell_list->slink;
  347. X        tfree(shell_list->scmd);
  348. X        tfree(shell_list);
  349. X        shell_list = shnext;
  350. X    }
  351. X
  352. X    /* restore our original globals */
  353. X    suffix_targ = tsuffix;
  354. X    target_list = thead;
  355. X    file_list = fhead;
  356. X    symbol_list = shead;
  357. X    shell_list = shhead;
  358. X    shell_cmds = shcmds;
  359. X    tlist = ttlist;
  360. X    now = tnow;
  361. X    opts = topts;
  362. X}
  363. X
  364. X
  365. X#ifndef    MSDOS
  366. Xint     spawnvp(mode, path, args)
  367. Xint     mode;
  368. Xchar   *path;
  369. Xchar  **args;
  370. X{
  371. X    int     pid = 0;
  372. X    int     retpid;
  373. X#ifdef    BSD
  374. X    union wait waitword;
  375. X#else
  376. X    int     waitword;
  377. X#endif
  378. X
  379. X    if (mode != P_OVERLAY)
  380. X        pid = fork();
  381. X
  382. X    if (pid == 0)
  383. X        execvp(path, args);
  384. X
  385. X    while (((retpid = wait(&waitword)) != pid) && (retpid > 0))
  386. X        ;
  387. X#ifdef    BSD
  388. X    return ((retpid == pid) ? waitword.w_retcode : (-1));
  389. X#else
  390. X    return ((retpid == pid) ? ((waitword >> 8) & 0x00ff) : (-1));
  391. X#endif
  392. X}
  393. X#endif
  394. END_OF_FILE
  395. if test 7577 -ne `wc -c <'build.c'`; then
  396.     echo shar: \"'build.c'\" unpacked with wrong size!
  397. fi
  398. # end of 'build.c'
  399. fi
  400. if test -f 'default.mk' -a "${1}" != "-c" ; then 
  401.   echo shar: Will not clobber existing file \"'default.mk'\"
  402. else
  403. echo shar: Extracting \"'default.mk'\" \(2487 characters\)
  404. sed "s/^X//" >'default.mk' <<'END_OF_FILE'
  405. X### this is the default makefile for Unix: default.mk
  406. X
  407. XSUFFIXES = .o .C .cxx .ec .c .y .l .s .sh 
  408. X.SUFFIXES: $(SUFFIXES)
  409. X
  410. X#    ASM section
  411. XAS     = as
  412. XASFLAGS     =
  413. XCOMPILE.s= $(AS) $(ASFLAGS)
  414. X.s:
  415. X    $(AS) $(ASFLAGS) $<
  416. X.s.o:
  417. X    $(AS) $(ASFLAGS) -o $@ $<
  418. X
  419. X#    C section
  420. XCC     = cc
  421. XCFLAGS     = -O
  422. XCDEBUG     = -g
  423. XCOMPILE.c= $(CC) $(CFLAGS) -c
  424. X.c:
  425. X    $(LINK.c) -o $@ $< $(LDFLAGS)
  426. X
  427. X.c.o:
  428. X    $(COMPILE.c) $<
  429. X
  430. X.c.i:
  431. X    $(COMPILE.c) -P $<
  432. X
  433. X#    CPP Section
  434. XCPP     = CC
  435. XCPPFLAGS = -O
  436. XCPPDEBUG = -g
  437. XCOMPILE.cpp = $(CPP) $(CPPFLAGS)
  438. X.C .cxx:
  439. X    $(CPP) $(CPPFLAGS) -o $@ $< $(LDFLAGS)
  440. X
  441. X.C.o .cxx.o:
  442. X    $(COMPILE.cpp) $<
  443. X
  444. X.C.c .cxx.c:
  445. X    $(COMPILE.cpp) -P $<
  446. X
  447. X#    ESQL/C section
  448. XESQL     = esql
  449. XEFLAGS     =
  450. XCOMPILE.e= $(ESQL) $(EFLAGS)
  451. X.ec:
  452. X    $(COMPILE.e) -e $<
  453. X    $(LINK.c) -o $@ $*.c $(LDFLAGS)
  454. X
  455. X.ec.o:
  456. X    $(COMPILE.e) -e $<
  457. X    $(COMPILE.c) $*.c
  458. X
  459. X.ec.c:
  460. X    $(COMPILE.e) -e $<
  461. X
  462. X#    Lex section
  463. XLEX     = lex
  464. XLFLAGS     =
  465. XLEX.l     = $(LEX) $(LFLAGS) -t
  466. X.l:
  467. X    $(LEX.l) $< > $*.c
  468. X    $(LINK.c) -o $@ $*.c $(LDFLAGS) -ll
  469. X
  470. X.l.o:
  471. X    $(LEX.l) $< > $*.c
  472. X    $(COMPILE.c) $*.c
  473. X
  474. X.l.c:
  475. X    $(LEX.l) $< > $*.c
  476. X
  477. X#    YACC section
  478. XYACC     = yacc
  479. XYFLAGS     =
  480. XYACC.y     = $(YACC) $(YFLAGS)
  481. X.y:
  482. X    $(YACC.y) $<
  483. X    $(LINK.c) -o $@ y.tab.c $(LDFLAGS) -ly
  484. X    $(RM) y.tab.c
  485. X
  486. X.y.o:
  487. X    $(YACC.y) $<
  488. X    $(COMPILE.c) -o $*.o y.tab.c
  489. X    $(RM) y.tab.c
  490. X
  491. X.y.c:
  492. X    $(YACC) $(YFLAGS) $<
  493. X    $(MV) y.tab.c $@
  494. X
  495. X.y.h:
  496. X    $(YACC) $(YFLAGS) -d $<
  497. X    $(RM) y.tab.c
  498. X    $(MV) y.tab.h $@
  499. X
  500. X#    Shell script section
  501. X.sh:
  502. X    cp $< $@
  503. X
  504. X#    BSD Unix Misc section
  505. XA        = .a
  506. XAR       = ar
  507. XARFLAGS  =
  508. XBIN      = /usr/local/bin
  509. XCP       = cp
  510. XE        =
  511. XEDITOR   = /usr/bin/vi
  512. XGFLAGS   =
  513. XGET      = get
  514. XLDEBUG   =
  515. XLDFLAGS  =
  516. XLD       = ld
  517. XLIBDIR   =
  518. XLINK.c   = $(CC) $(CFLAGS)
  519. XMAKE     = make
  520. XMKDEPEND = makedepend
  521. XMODEL    =
  522. XMV       = mv
  523. XO        = .o
  524. XRANLIB   = ranlib
  525. XRM       = rm -f
  526. XSHELL    = /bin/csh
  527. XSHELLCMD =
  528. XSTACK    =
  529. X
  530. X#    DOS Misc section
  531. X#A        = .lib
  532. X#AR       = lib
  533. X#ARFLAGS  =
  534. X#BIN      = C:\bin
  535. X#CP       = cp
  536. X#E        = .exe
  537. X#EDITOR   = $(BIN)\vi
  538. X#GFLAGS   =
  539. X#GET      = echo cannot get
  540. X#LDEBUG   = /link /noe /noi /co /st:$(STACK) $(LIBS)
  541. X#LDFLAGS  = /link /noe /noi /st:$(STACK) $(LIBS)
  542. X#LD       = $(CC) $(CFLAGS)
  543. X#LIBDIR   = c:\msc5.1\lib
  544. X#LINK.c   = $(CC) $(CFLAGS)
  545. X#MAKE     = make
  546. X#MKDEPEND = mkdepend
  547. X#MODEL    = S
  548. X#MV       = mv
  549. X#O        = .o
  550. X#RANLIB   = echo cannot ranlib 
  551. X#RM       = rm -f
  552. X#SHELL    = command /c
  553. X#SHELLCMD = break call cd chcp chdir cls copy ctty date del dir \
  554. X#       echo erase exit for goto if md mkdir path pause prompt \
  555. X#       rd rem ren rename rmdir set shift time type ver verify vol
  556. X#STACK    = 2000
  557. END_OF_FILE
  558. if test 2487 -ne `wc -c <'default.mk'`; then
  559.     echo shar: \"'default.mk'\" unpacked with wrong size!
  560. fi
  561. # end of 'default.mk'
  562. fi
  563. if test -f 'default.msc' -a "${1}" != "-c" ; then 
  564.   echo shar: Will not clobber existing file \"'default.msc'\"
  565. else
  566. echo shar: Extracting \"'default.msc'\" \(3930 characters\)
  567. sed "s/^X//" >'default.msc' <<'END_OF_FILE'
  568. X### this is the default makefile for DOS: default.mk
  569. X
  570. XSUFFIXES = .cpp .c .asm .l .y .ec
  571. X.SUFFIXES: $(SUFFIXES)
  572. X
  573. X#    ASM section
  574. XAS     = masm
  575. XASFLAGS     = /mx            # don't convert to upper case
  576. XCOMPILE.s= $(AS) $(ASFLAGS)
  577. X.asm .asm.com:
  578. X     $(COMPILE.s) $<;
  579. X     $(LINK.c) -o $*.exe $*.obj $(LDFLAGS)
  580. X     $(RM) $*.obj
  581. X     exe2bin $*.exe $*.com
  582. X     $(RM) $*.exe
  583. Xasm.exe:
  584. X     $(COMPILE.s) $<;
  585. X     $(LINK.c) -o $@ $*.obj $(LDFLAGS)
  586. X     $(RM) $*.obj
  587. X.asm.obj:
  588. X     $(COMPILE.s) $<;
  589. X.asm.o:
  590. X     $(COMPILE.s) $<;
  591. X     mv $*.obj $@
  592. X
  593. X#    C section
  594. XCC     = cl -A$(MODEL)
  595. XCFLAGS     = /Ox /G2        # full optimization, 80286 opcodes
  596. XCDEBUG     = /Od /Zi        # no optimization, Codeview debuggable
  597. XCOMPILE.c= $(CC) $(CFLAGS) -c
  598. X.c.com:
  599. X     $(COMPILE.cpp) -mt $< $(LIBS)
  600. X     $(RM) $*.obj
  601. X.c .c.exe:
  602. X     $(LINK.c) -o $@ $< $(LDFLAGS)
  603. X     $(RM) $*.obj
  604. X.c.o:
  605. X     $(COMPILE.c) /Fo$*.o $<
  606. X.c.obj:
  607. X     $(COMPILE.c) $<
  608. X
  609. X#    D section (ANSI C declaration headers)
  610. X.c.d:
  611. X     echo "#ifndef NOPROTOTYPES" > $*.tmp
  612. X    -$(COMPILE.c) -DNOPROTOTYPES -Zg $< >> $*.tmp
  613. X     echo "#endif" >> $*.tmp
  614. X    +updexhdr $*.tmp $*.d
  615. X     $(RM) $*.tmp
  616. X
  617. X#    I section (preprocessed C files)
  618. X.c.i:
  619. X     $(COMPILE.c) -P $<
  620. X
  621. X#    CPP Section
  622. XCPPINCDIR= c:\zortech\include
  623. XCPP     = ztc -DNO_EXT_KEYS -I$(CPPINCDIR) -B -m$(MODEL)i    # integer only
  624. XCPPF     = ztc -DNO_EXT_KEYS -I$(CPPINCDIR) -B -m$(MODEL)    # floats also
  625. XCPPFLAGS = -o                    # full optimization
  626. XCPPDEBUG = -g -co -s                # codeview and stack checking
  627. XCOMPILE.cpp=$(CPP) $(CPPFLAGS)
  628. X.cpp .cpp.com:
  629. X     $(COMPILE.cpp) -mt $<
  630. X     $(RM) $*.obj
  631. X.cpp.exe:
  632. X     $(COMPILE.cpp) $<
  633. X     $(RM) $*.obj
  634. X.cpp.obj:
  635. X     $(COMPILE.cpp) -c $<
  636. X.cpp.o:
  637. X     $(COMPILE.cpp) -c $<
  638. X     $(MV) $*.obj $@
  639. X.cpp.c:
  640. X    $(COMPILE.cpp) -c -e -l$*.c $<
  641. X
  642. X#    ESQL/C section
  643. XESQL     = esql
  644. XEFLAGS     =
  645. XCOMPILE.e= $(ESQL) $(EFLAGS)
  646. X.ec .ec.exe:
  647. X     $(COMPILE.e) -e $<
  648. X     $(LINK.c) -o $@ $*.c $(LDFLAGS) $(MODEL)libsql
  649. X     $(RM) $*.obj $*.c
  650. X.ec.o:
  651. X     $(COMPILE.e) -e $<
  652. X     $(COMPILE.c) /Fo$*.o $*.c
  653. X     $(RM) $*.c
  654. X.ec.obj:
  655. X     $(COMPILE.e) -e $<
  656. X     $(COMPILE.c) $*.c
  657. X     $(RM) $*.c
  658. X.ec.c:
  659. X     $(COMPILE.e) -e $<
  660. X
  661. X#    Lex section
  662. XLEX     = flex
  663. XLFLAGS     = -I                # interactive scanner
  664. XLEX.l     = $(LEX) $(LFLAGS) -t
  665. X.l.com:
  666. X     $(LEX.l) $< > $*.c
  667. X     $(COMPILE.cpp) -mt $*.c
  668. X     $(RM) $*.obj $*.c
  669. X.l .l.exe:
  670. X     $(LEX.l) $< > $*.c
  671. X     $(LINK.c) -o $@ $*.c $(LDFLAGS)
  672. X     $(RM) $*.obj $*.c
  673. X.l.o:
  674. X     $(LEX.l) $< > $*.c
  675. X     $(COMPILE.c) /Fo$*.o $*.c
  676. X     $(RM) $*.c
  677. X.l.obj:
  678. X     $(LEX.l) $< > $*.c
  679. X     $(COMPILE.c) $*.c
  680. X     $(RM) $*.c
  681. X.l.c:
  682. X     $(LEX.l) $< > $@
  683. X
  684. X#    YACC Section
  685. XYACC     = yacc
  686. XYFLAGS     =
  687. XYACC.y     = $(YACC) $(YFLAGS)
  688. X.y.com:
  689. X     $(YACC.y) $<
  690. X     $(COMPILE.cpp) -mt ytab.c
  691. X     $(RM) $*.obj ytab.c
  692. X.y .y.exe:
  693. X     $(YACC.y) $<
  694. X     $(LINK.c) -o $@ ytab.c $(LDFLAGS)
  695. X     $(RM) $*.obj ytab.c
  696. X.y.o:
  697. X     $(YACC.y) $<
  698. X     $(COMPILE.c) /Fo$*.o ytab.c
  699. X     $(RM) ytab.c
  700. X.y.obj:
  701. X     $(YACC.y) $<
  702. X     $(COMPILE.c) ytab.c
  703. X     $(RM) ytab.c
  704. X.y.h:
  705. X     $(YACC.y) -d $<
  706. X     $(RM) ytab.c
  707. X     $(MV) ytab.h $@
  708. X.y.c:
  709. X     $(YACC.y) $<
  710. X     $(MV) ytab.c $@
  711. X
  712. X#    BSD Unix Misc section
  713. X#A        = .a
  714. X#AR       = ar
  715. X#ARFLAGS  =
  716. X#BIN      = /usr/local/bin
  717. X#CP       = cp
  718. X#E        =
  719. X#EDITOR   = /usr/bin/vi
  720. X#GFLAGS   =
  721. X#GET      = get
  722. X#LDEBUG   =
  723. X#LDFLAGS  =
  724. X#LD       = ld
  725. X#LIBDIR   =
  726. X#LINK.c   = $(CC) $(CFLAGS)
  727. X#MAKE     = make
  728. X#MKDEPEND = makedepend
  729. X#MODEL    =
  730. X#MV       = mv
  731. X#O        = .o
  732. X#RANLIB   = ranlib
  733. X#RM       = rm -f
  734. X#SHELL    = /bin/csh
  735. X#SHELLCMD =
  736. X#STACK    =
  737. X
  738. X#    DOS Misc section
  739. XA        = .lib
  740. XAR       = lib
  741. XARFLAGS  =
  742. XBIN      = C:\bin
  743. XCP       = cp
  744. XE        = .exe
  745. XEDITOR   = $(BIN)\vi
  746. XGFLAGS   =
  747. XGET      = echo cannot get
  748. XLDEBUG   = /link /noe /noi /co /st:$(STACK) $(LIBS)
  749. XLDFLAGS  = /link /noe /noi /st:$(STACK) $(LIBS)
  750. XLD       = $(CC) $(CFLAGS)
  751. XLIBDIR   = c:\msc5.1\lib
  752. XLINK.c   = $(CC) $(CFLAGS)
  753. XMAKE     = make
  754. XMKDEPEND = mkdepend
  755. XMODEL    = S
  756. XMV       = mv
  757. XO        = .o
  758. XRANLIB   = echo cannot ranlib 
  759. XRM       = rm -f
  760. XSHELL    = command /c
  761. XSHELLCMD = break call cd chcp chdir cls copy ctty date del dir \
  762. X       echo erase exit for goto if md mkdir path pause prompt \
  763. X       rd rem ren rename rmdir set shift time type ver verify vol
  764. XSTACK    = 2000
  765. END_OF_FILE
  766. if test 3930 -ne `wc -c <'default.msc'`; then
  767.     echo shar: \"'default.msc'\" unpacked with wrong size!
  768. fi
  769. # end of 'default.msc'
  770. fi
  771. if test -f 'make.h' -a "${1}" != "-c" ; then 
  772.   echo shar: Will not clobber existing file \"'make.h'\"
  773. else
  774. echo shar: Extracting \"'make.h'\" \(3424 characters\)
  775. sed "s/^X//" >'make.h' <<'END_OF_FILE'
  776. X/*
  777. X * make.h
  778. X *
  779. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  780. X * 88-10-06 v1.1    changed prerequisite list handling
  781. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  782. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  783. X * 89-08-01 v1.4 AB    lots of new options and code
  784. X * 89-10-30 v1.5    -f -S -q options, took some changes from v1.4
  785. X * 90-04-18 v1.6    -b -- -W options, emulate <<, non-BSD cleanup
  786. X */
  787. X
  788. X#define MAKEINI "default.mk"
  789. X
  790. X#ifdef    MSDOS
  791. X#define    PATH_SEPARATOR    ";"
  792. X#define    FILE_SEPARATOR    ":/\\"
  793. X#define    SHELL_METAS    "<|>"
  794. X#else
  795. X#define    PATH_SEPARATOR    ":"
  796. X#define    FILE_SEPARATOR    "/"
  797. X#define    SHELL_METAS    "<|>`*?()[];&$"
  798. X#endif
  799. X
  800. X#define    MAXNEGTIME    0x80000000
  801. X
  802. X#define    equal(s,t)        (!strcmp((s),(t)))
  803. X#define    get_target(t)        hash_target((t), NULL)
  804. X#define    get_file(f)        hash_file((f), NULL)
  805. X#define    append_preq(t,p)    (fileptr*)append_node((char**)(t),(char**)(p),sizeof(fileptr*))
  806. X#define    append_shell(t,s)    (shellptr*)append_node((char**)(t),(char**)(s),sizeof(shellptr*))
  807. X
  808. Xtypedef unsigned short t_mask;
  809. X
  810. Xtypedef struct targnode
  811. X{
  812. X    t_mask  tmask;        /* mask to avoid string compares */
  813. X    struct targnode *tnext;    /* next target in global target list */
  814. X    struct filenode *tfile;    /* file node for this target */
  815. X    struct filenode **tpreq;/* pre-req list for this target */
  816. X    struct shellnode **tshell;    /* command list for this target */
  817. X}       targnode, *targptr;
  818. X
  819. Xtypedef struct filenode
  820. X{
  821. X    t_mask  fmask;        /* mask to avoid string compares */
  822. X    char   *fname;        /* name of this file (targ, preq...) */
  823. X    long    ftime;        /* last MODIFY time for this file */
  824. X    struct filenode *fnext;    /* next file node in global file list */
  825. X}       filenode, *fileptr;
  826. X
  827. Xtypedef struct shellnode
  828. X{
  829. X    char   *scmd;        /* text of command */
  830. X    unsigned s_silent:1;    /* don't echo before executing */
  831. X    unsigned s_ignore:1;    /* ignore exit status */
  832. X    unsigned s_shell:1;    /* force spawning of command.com */
  833. X    struct shellnode *slink;/* next shell node in global list */
  834. X}       shellnode, *shellptr;
  835. X
  836. Xtypedef struct symnode
  837. X{
  838. X    t_mask  smask;        /* mask to avoid string compares */
  839. X    char   *sname;        /* name of a symbol */
  840. X    char   *svalue;        /* value of a symbol */
  841. X    struct symnode *snext;    /* next symbol node in global list */
  842. X    int     scmd;        /* command line macro? */
  843. X    int     slevel;        /* level of new_make() */
  844. X}       symnode, *symptr;
  845. X
  846. Xtypedef struct optnode
  847. X{
  848. X    unsigned depend;    /* -d */
  849. X    unsigned display:1;    /* -D */
  850. X    unsigned envirn:1;    /* -e */
  851. X    unsigned ignore:1;    /* -i */
  852. X    unsigned keepon:1;    /* -k */
  853. X    unsigned noexec:1;    /* -n */
  854. X    unsigned query:1;    /* -q */
  855. X    unsigned silent:1;    /* -s */
  856. X    unsigned touch:1;    /* -t */
  857. X    char   *make;        /* current value of $(MAKE) */
  858. X}       optnode;
  859. X
  860. Xextern targptr target_list;    /* global list of targets */
  861. Xextern fileptr file_list;    /* global list of file nodes */
  862. Xextern symptr symbol_list;    /* global list of symbol nodes */
  863. Xextern shellptr shell_list;    /* global list of shell nodes */
  864. X
  865. Xextern char **shell_cmds;    /* commands which force usage of SHELL */
  866. X
  867. Xextern int make_level;        /* level of new_make() */
  868. X
  869. Xextern targptr first_targ;    /* first target (if nothing named) */
  870. Xextern targptr suffix_targ;    /* target node of ".SUFFIXES" */
  871. X
  872. Xextern optnode opts;        /* various options */
  873. Xextern char **tlist;        /* list of command line targets */
  874. Xextern long now;        /* current time */
  875. X
  876. X#ifndef    MSDOS
  877. Xchar   *getenv();
  878. X
  879. X#define    P_WAIT        1
  880. X#define    P_NOWAIT    2
  881. X#define    P_OVERLAY    3
  882. X#endif                /* MSDOS */
  883. END_OF_FILE
  884. if test 3424 -ne `wc -c <'make.h'`; then
  885.     echo shar: \"'make.h'\" unpacked with wrong size!
  886. fi
  887. # end of 'make.h'
  888. fi
  889. if test -f 'makefile' -a "${1}" != "-c" ; then 
  890.   echo shar: Will not clobber existing file \"'makefile'\"
  891. else
  892. echo shar: Extracting \"'makefile'\" \(1286 characters\)
  893. sed "s/^X//" >'makefile' <<'END_OF_FILE'
  894. X# name of this program
  895. XNAME    = make
  896. X
  897. X# define the FLAGS as required for MSDOS or Unix
  898. XCFLAGS    = -O
  899. XLDFLAGS    =
  900. X
  901. XSRCS    = make.c parse.c build.c tstring.c
  902. XOBJS    = make.o parse.o build.o tstring.o
  903. XPROG    = $(NAME)$E
  904. X
  905. X# define your installation directory
  906. XBIN    = $(HOME)/bin
  907. X
  908. X# archive utility
  909. XARCADD    = zoo a
  910. X
  911. X# files to archive
  912. XARCS    = decl.h make.h tstring.h make.c parse.c build.c tstring.c \
  913. X      default.mk default.bsd makefile makefile.bsd make.doc \
  914. X      README $(PROG)
  915. X
  916. Xall:    $(PROG)
  917. X
  918. X$(PROG):    $(OBJS)
  919. X    $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LDFLAGS)
  920. X
  921. Xarc:    $(NAME).zoo
  922. Xzoo:    $(NAME).zoo
  923. X
  924. X$(NAME).zoo:    $(ARCS)
  925. X    $(RM) $(NAME).zoo
  926. X    $(ARCADD) $(NAME).zoo $(ARCS)
  927. X
  928. Xinstall:    $(BIN)/$(PROG) $(BIN)/default.mk
  929. X$(BIN)/$(PROG):    $(PROG)
  930. X    cp $(PROG) $(BIN)/$(PROG)
  931. X$(BIN)/default.mk: default.mk
  932. X    cp default.mk $(BIN)/default.mk
  933. X
  934. Xclean:
  935. X    -$(RM) *.o
  936. X    -$(RM) *.bak
  937. X
  938. X# use this to check the size of the program (use chkdsk if necessary)
  939. Xsize:
  940. X    pmap
  941. X
  942. Xdepend:
  943. X    $(MKDEPEND) $(SRCS) > makefile.new
  944. X    $(MV) makefile makefile.BAK
  945. X    $(MV) makefile.new makefile
  946. X
  947. Xtest:    $(OBJS)
  948. X    link @<<END_OF_LINK
  949. X        $(OBJS)
  950. X        x$(NAME)
  951. X        /cparmaxalloc:1 /noe /stack:2000
  952. X        $(LIBS)
  953. X    END_OF_LINK
  954. X
  955. X# DO NOT DELETE THIS LINE
  956. X
  957. Xmake.o: make.h tstring.h decl.h 
  958. Xparse.o: make.h tstring.h decl.h 
  959. Xbuild.o: make.h tstring.h decl.h
  960. Xtstring.o: tstring.h 
  961. END_OF_FILE
  962. if test 1286 -ne `wc -c <'makefile'`; then
  963.     echo shar: \"'makefile'\" unpacked with wrong size!
  964. fi
  965. # end of 'makefile'
  966. fi
  967. if test -f 'makefile.msc' -a "${1}" != "-c" ; then 
  968.   echo shar: Will not clobber existing file \"'makefile.msc'\"
  969. else
  970. echo shar: Extracting \"'makefile.msc'\" \(1483 characters\)
  971. sed "s/^X//" >'makefile.msc' <<'END_OF_FILE'
  972. X# name of this program
  973. XNAME    = make
  974. X
  975. X# define the FLAGS as required for MSDOS or Unix
  976. XCFLAGS    = /Oals /Gs /G2
  977. XLDFLAGS = /link /cparmaxalloc:1 /noe /stack:2000 $(LIBS)
  978. X
  979. XSRCS    = make.c parse.c build.c tstring.c
  980. XOBJS    = make.o parse.o build.o tstring.o
  981. XPROG    = $(NAME)$E
  982. X
  983. X# define your installation directory
  984. XBIN    = c:/bin
  985. X
  986. X# archive utility
  987. XARCADD    = zoo a
  988. X
  989. X# files to archive
  990. XARC1    = decl.h make.h tstring.h make.c parse.c build.c tstring.c default.mk
  991. XARC2    = default.bsd makefile makefile.bsd make.doc README $(PROG)
  992. XARCS    = $(ARC1) $(ARC2)
  993. X
  994. Xall:    $(PROG)
  995. X
  996. X$(PROG):    $(OBJS)
  997. X    echo out of date dependents($@): $?
  998. X    $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LDFLAGS)
  999. X
  1000. Xarc:    $(NAME).zoo
  1001. Xzoo:    $(NAME).zoo
  1002. X
  1003. X$(NAME).zoo:    $(ARCS)
  1004. X    $(RM) $(NAME).zoo
  1005. X    $(ARCADD) $(NAME).zoo $(ARC1)
  1006. X    $(ARCADD) $(NAME).zoo $(ARC2)
  1007. X
  1008. Xinstall:    $(BIN)/$(PROG) $(BIN)/default.mk
  1009. X$(BIN)/$(PROG):    $(PROG)
  1010. X    cp $(PROG) $(BIN)/$(PROG)
  1011. X$(BIN)/default.mk: default.mk
  1012. X    cp default.mk $(BIN)/default.mk
  1013. X
  1014. Xclean:
  1015. X    -$(RM) *.o
  1016. X    -$(RM) *.bak
  1017. X
  1018. X# use this to check the size of the program (use chkdsk if necessary)
  1019. Xsize:
  1020. X    pmap
  1021. X
  1022. Xdepend:
  1023. X    $(MKDEPEND) $(SRCS) > makefile.new
  1024. X    $(MV) makefile makefile.BAK
  1025. X    $(MV) makefile.new makefile
  1026. X
  1027. Xtest:    $(OBJS)
  1028. X    echo out of date dependents($@): $?
  1029. X    link @<<END_OF_LINK
  1030. X        $(OBJS)
  1031. X        x$(NAME)
  1032. X        /cparmaxalloc:1 /noe /stack:2000
  1033. X        $(LIBS)
  1034. X    END_OF_LINK
  1035. X    echo End Of Link
  1036. X
  1037. X# DO NOT DELETE THIS LINE
  1038. X
  1039. Xmake.o: make.h tstring.h decl.h 
  1040. Xparse.o: make.h tstring.h decl.h 
  1041. Xbuild.o: make.h tstring.h decl.h 
  1042. Xtstring.o: tstring.h 
  1043. END_OF_FILE
  1044. if test 1483 -ne `wc -c <'makefile.msc'`; then
  1045.     echo shar: \"'makefile.msc'\" unpacked with wrong size!
  1046. fi
  1047. # end of 'makefile.msc'
  1048. fi
  1049. if test -f 'parse.c' -a "${1}" != "-c" ; then 
  1050.   echo shar: Will not clobber existing file \"'parse.c'\"
  1051. else
  1052. echo shar: Extracting \"'parse.c'\" \(17139 characters\)
  1053. sed "s/^X//" >'parse.c' <<'END_OF_FILE'
  1054. X/*
  1055. X * parse.c
  1056. X *
  1057. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  1058. X * 88-10-06 v1.1    changed prerequisite list handling
  1059. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  1060. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  1061. X * 89-08-01 v1.4 AB    lots of new options and code
  1062. X * 89-10-30 v1.5    -f -S -q options, took some changes from v1.4
  1063. X * 90-04-18 v1.6    -b -- -W options, emulate <<, non-BSD cleanup
  1064. X */
  1065. X#include <stdio.h>
  1066. X#include <ctype.h>
  1067. X#include <string.h>
  1068. X#ifdef    MSDOS
  1069. X#include <stdlib.h>
  1070. X#endif
  1071. X
  1072. X#include "make.h"
  1073. X#include "tstring.h"
  1074. X#include "decl.h"
  1075. X
  1076. X/*
  1077. X * parse    - read (text) makefile, and parse
  1078. X *        - close file before returing
  1079. X *
  1080. X * lines have the following format:
  1081. X *    # with or without preceeding spaces/tabs    (comment line)
  1082. X *    <TAB> commands                    (shell line)
  1083. X *    name = stuff                    (macro)
  1084. X *    name += stuff                    (macro)
  1085. X *    targ [targ...] : [pre-req...] [; shell cmd ]    (target line)
  1086. X */
  1087. Xparse(fd)
  1088. XFILE   *fd;
  1089. X{
  1090. X    char   *input;
  1091. X    char   *ip;
  1092. X    char   *colonp;
  1093. X    char    schar;
  1094. X    int     ntargs, npreqs, nshell;
  1095. X    int     tmax, pmax, smax;
  1096. X    targptr *targs;
  1097. X    fileptr *preqs;
  1098. X    shellptr *shells;
  1099. X
  1100. X    if (fd == NULL)
  1101. X        return (0);
  1102. X
  1103. X    /* start off with a short list of targets */
  1104. X    targs = (targptr *) grow_list(NULL, &tmax);
  1105. X    preqs = (fileptr *) grow_list(NULL, &pmax);
  1106. X    shells = (shellptr *) grow_list(NULL, &smax);
  1107. X
  1108. X    ntargs = npreqs = nshell = 0;
  1109. X
  1110. X    /* maximize buffering */
  1111. X    setvbuf(fd, NULL, _IOFBF, 2048);
  1112. X
  1113. X    while ((input = tgets(fd)) != NULL)
  1114. X    {
  1115. X        /* punt on comments and blank lines */
  1116. X        for (ip = input; isspace(*ip); ++ip);
  1117. X        if (*ip == '#' || *ip == '\0')
  1118. X            continue;
  1119. X
  1120. X        /* process include files */
  1121. X        if (!strncmp(ip, "include", 7))
  1122. X        {
  1123. X            /* skip spaces AFTER "include" */
  1124. X            for (ip += 7; isspace(*ip); ++ip);
  1125. X
  1126. X            /* process macros in the filename */
  1127. X            ip = breakout(ip);
  1128. X
  1129. X            /* parse the makefile */
  1130. X            if (!parse(fopen(ip, "r")))
  1131. X                terror(1, tstrcat("cannot open ", ip));
  1132. X
  1133. X            /* free up the broken-out string */
  1134. X            tfree(ip);
  1135. X            continue;    /* get next input line */
  1136. X        }
  1137. X
  1138. X        /* display the makefile line ? */
  1139. X        if (opts.display)
  1140. X            puts(input);
  1141. X
  1142. X        /* get rid of comments and preceeding spaces */
  1143. X        for (colonp = ip; *colonp && *colonp != '#'; ++colonp)
  1144. X        {
  1145. X            if (*colonp == '\'' || *colonp == '"')
  1146. X                colonp = tstrspan(colonp);
  1147. X        }
  1148. X
  1149. X        for (--colonp; colonp >= ip && isspace(*colonp); --colonp);
  1150. X
  1151. X        /* we *know* that some non-space is on this line, from above */
  1152. X        if (colonp >= ip)
  1153. X            *++colonp = '\0';
  1154. X
  1155. X        /* see if we have a shell command */
  1156. X        if (isspace(*input))
  1157. X        {
  1158. X            if (ntargs == 0)
  1159. X                terror(1, "rules must be after target");
  1160. X    got_shell:
  1161. X            if (nshell == smax)
  1162. X            {
  1163. X                shells = (shellptr *)
  1164. X                    grow_list((char **) shells, &smax);
  1165. X            }
  1166. X            shells[nshell++] = add_shell(ip);
  1167. X            continue;
  1168. X        }
  1169. X
  1170. X        /* not a shell line, so must be a target or a macro */
  1171. X        if (ntargs != 0)
  1172. X        {
  1173. X            /* link previous preq's and shell's */
  1174. X            targs[ntargs] = NULL;
  1175. X            preqs[npreqs] = NULL;
  1176. X            shells[nshell] = NULL;
  1177. X            link_targs(targs, preqs, shells);
  1178. X            ntargs = npreqs = nshell = 0;
  1179. X        }
  1180. X
  1181. X        /* don't break out symbols until macro is invoked */
  1182. X        if (add_macro(ip, 0))
  1183. X            continue;
  1184. X
  1185. X        /* okay, we have a target line; break out macro symbols */
  1186. X        input = breakout(ip);
  1187. X
  1188. X        /* just look for tokens with standard isspace() separators */
  1189. X        ip = token(input, NULL, &schar);
  1190. X        while (ip)
  1191. X        {
  1192. X            colonp = strchr(ip, ':');
  1193. X#ifdef    MSDOS
  1194. X            /* need to allow c:/bin/make.exe as a target */
  1195. X            if (colonp && colonp - ip == 1)
  1196. X                colonp = strchr(colonp + 1, ':');
  1197. X#endif
  1198. X            if (colonp)
  1199. X            {
  1200. X                /* got a separator */
  1201. X                *colonp = '\0';
  1202. X
  1203. X                /* if at front of token, target is done */
  1204. X                if (colonp == ip)
  1205. X                    break;
  1206. X            }
  1207. X
  1208. X            if (ntargs == tmax)
  1209. X                targs = (targptr *) grow_list((char **) targs,
  1210. X                                  &tmax);
  1211. X            targs[ntargs] = add_target(ip);
  1212. X
  1213. X            /* make sure we don't save .INIT as our 1st target */
  1214. X            if (first_targ == NULL && *ip != '.')
  1215. X                first_targ = targs[ntargs];
  1216. X            ++ntargs;
  1217. X
  1218. X            if (colonp)
  1219. X                break;
  1220. X            ip = token(NULL, NULL, &schar);
  1221. X        }
  1222. X
  1223. X        /* a target line without a colon?  naughty, naughty! */
  1224. X        if (!colonp)
  1225. X            terror(-1, "Unexpected end of line seen");
  1226. X
  1227. X/*
  1228. X *         taking care of four possible cases:
  1229. X *            1)    object : source
  1230. X *            2)    object: source
  1231. X *            3)    object :source
  1232. X *            4)    object:source
  1233. X */
  1234. X
  1235. X        if (colonp && *++colonp)
  1236. X            ip = colonp;
  1237. X        else
  1238. X            ip = token(NULL, NULL, &schar);
  1239. X
  1240. X        /* link the pre-req's */
  1241. X        while (ip)
  1242. X        {
  1243. X            if ((colonp = strchr(ip, ';')) != NULL)
  1244. X            {
  1245. X                ip[strlen(ip)] = schar;
  1246. X                *colonp = '\0';
  1247. X            }
  1248. X
  1249. X            if (*ip)
  1250. X            {
  1251. X                if (npreqs == pmax)
  1252. X                {
  1253. X                    preqs = (fileptr *)
  1254. X                        grow_list((char **) preqs,
  1255. X                              &pmax);
  1256. X                }
  1257. X
  1258. X                preqs[npreqs++] = add_file(ip);
  1259. X            }
  1260. X
  1261. X            if (colonp)
  1262. X            {
  1263. X                ip = colonp + 1;
  1264. X                goto got_shell;
  1265. X            }
  1266. X
  1267. X            ip = token(NULL, NULL, &schar);
  1268. X        }
  1269. X
  1270. X        /* gotta free the line allocated by breakout() */
  1271. X        tfree(input);
  1272. X    }
  1273. X
  1274. X    /* link up any dangling dependants */
  1275. X    if (ntargs != 0)
  1276. X    {
  1277. X        targs[ntargs] = NULL;
  1278. X        preqs[npreqs] = NULL;
  1279. X        shells[nshell] = NULL;
  1280. X        link_targs(targs, preqs, shells);
  1281. X    }
  1282. X
  1283. X    /* clean up our mallocs */
  1284. X    tfree(targs);
  1285. X    tfree(preqs);
  1286. X    tfree(shells);
  1287. X
  1288. X    fclose(fd);
  1289. X    return (1);
  1290. X}
  1291. X
  1292. X
  1293. X/*
  1294. X * link_targs    - force a list of targs to point to same preq's and shell's
  1295. X */
  1296. Xlink_targs(targs, preqs, shells)
  1297. Xtargptr *targs;
  1298. Xfileptr *preqs;
  1299. Xshellptr *shells;
  1300. X{
  1301. X    while (targs && *targs)
  1302. X    {
  1303. X        /* process some special targets */
  1304. X        if ((*targs)->tfile->fname[0] == '.')
  1305. X        {
  1306. X            if (equal((*targs)->tfile->fname, ".SILENT"))
  1307. X                opts.silent = 1;
  1308. X            else
  1309. X            if (equal((*targs)->tfile->fname, ".IGNORE"))
  1310. X                opts.ignore = 1;
  1311. X            else
  1312. X            if (equal((*targs)->tfile->fname, ".SUFFIXES"))
  1313. X                /*
  1314. X                 * set `suffix_targ' to speed up
  1315. X                 * `default_rule' 
  1316. X                 */
  1317. X                suffix_targ = *targs;
  1318. X
  1319. X            /* special rule has preq's reset */
  1320. X            /* normally, preq's are merely appended */
  1321. X            if (*preqs == NULL && (*targs)->tpreq != NULL)
  1322. X            {
  1323. X                tfree((*targs)->tpreq);
  1324. X                (*targs)->tpreq = NULL;
  1325. X            }
  1326. X
  1327. X            /* special rules have their shell commands replaced */
  1328. X            if ((*targs)->tshell != NULL && *shells != NULL)
  1329. X            {
  1330. X                shellptr *sp;
  1331. X
  1332. X                for (sp = (*targs)->tshell; *sp; ++sp)
  1333. X                    tfree(*sp);
  1334. X                tfree((*targs)->tshell);
  1335. X                (*targs)->tshell = NULL;
  1336. X            }
  1337. X        }
  1338. X
  1339. X        /* each target in the list points to the preq's and shell's */
  1340. X        (*targs)->tpreq = append_preq((*targs)->tpreq, preqs);
  1341. X
  1342. X        /* we cannot expand the list of shell commands */
  1343. X        if ((*targs)->tshell != NULL && *shells != NULL)
  1344. X        {
  1345. X            terror(1, tstrcat("Too many rules defined for target ",
  1346. X                      (*targs)->tfile->fname));
  1347. X        }
  1348. X        (*targs)->tshell = append_shell((*targs)->tshell, shells);
  1349. X        ++targs;
  1350. X    }
  1351. X}
  1352. X
  1353. X
  1354. X/* macros must have the format: WORD = more stuff
  1355. X *                     WORD= more stuff
  1356. X *                WORD =more stuff
  1357. X *                WORD=more stuff
  1358. X *            or:    WORD += more stuff
  1359. X *                WORD +=more stuff
  1360. X *
  1361. X * it is assumed that there is no leading whitespace in `input'
  1362. X */
  1363. Xadd_macro(input, scmd)
  1364. Xchar   *input;
  1365. Xint     scmd;
  1366. X{
  1367. X    char   *eqsign;
  1368. X    char   *value;
  1369. X    symptr  symp;
  1370. X
  1371. X    /* gotta have an '=' to be a macro */
  1372. X    eqsign = strchr(input, '=');
  1373. X    if (eqsign == NULL)
  1374. X        return (0);
  1375. X
  1376. X    /* make sure we catch imbedded '='s (e.g. MACRO=STUFF) */
  1377. X    for (value = input; *value && !isspace(*value); ++value);
  1378. X    if (value > eqsign)
  1379. X        value = eqsign;
  1380. X
  1381. X    /* terminate the macro name */
  1382. X    *value = '\0';
  1383. X
  1384. X    /* find start of value */
  1385. X    for (value = eqsign + 1; isspace(*value); ++value);
  1386. X
  1387. X    /* look for concat character */
  1388. X    --eqsign;
  1389. X
  1390. X    if (eqsign < input || (eqsign == input && *eqsign == '+'))
  1391. X        terror(1, "Badly formed macro");
  1392. X
  1393. X    if (*eqsign == '+')
  1394. X    {
  1395. X        /* append to the current macro definition */
  1396. X        *eqsign = '\0';
  1397. X        symp = get_symbol(input, scmd);
  1398. X        if (symp->scmd && !scmd)
  1399. X            return (1);
  1400. X        if (symp->slevel < make_level)
  1401. X            symp = dup_symbol(symp, symp->svalue);
  1402. X        if (symp->svalue)
  1403. X        {
  1404. X            eqsign = tstrcat(symp->svalue, " ");
  1405. X            value = tstrcat(eqsign, value);
  1406. X            tfree(eqsign);
  1407. X            tfree(symp->svalue);
  1408. X            symp->svalue = value;
  1409. X            return (1);
  1410. X        }
  1411. X    }
  1412. X
  1413. X    add_symbol(input, value, scmd);
  1414. X    return (1);
  1415. X}
  1416. X
  1417. X
  1418. X/*
  1419. X * add_symbol    - add a <name,value> pair to the symbol table
  1420. X *        - override existing symbol value
  1421. X *        - mark as either command-line macro or not
  1422. X */
  1423. Xadd_symbol(name, value, scmd)
  1424. Xchar   *name;
  1425. Xchar   *value;
  1426. Xint     scmd;
  1427. X{
  1428. X    symptr  symp;
  1429. X
  1430. X    symp = get_symbol(name, scmd);
  1431. X    if (symp->scmd & !scmd)
  1432. X        return;
  1433. X    if (symp->slevel < make_level)
  1434. X        symp = dup_symbol(symp, NULL);    /* don't dup the value */
  1435. X    if (symp->svalue)
  1436. X        tfree(symp->svalue);
  1437. X    symp->svalue = tstrcpy(value);
  1438. X    symp->scmd = scmd;
  1439. X}
  1440. X
  1441. X
  1442. X/*
  1443. X * get_symbol    - find a symbol in the symbol table
  1444. X *        - if non-extant, create <name,NULL>
  1445. X *        - return created or found symbol node
  1446. X */
  1447. Xsymptr  get_symbol(name, scmd)
  1448. Xchar   *name;
  1449. Xint     scmd;
  1450. X{
  1451. X    symptr  symp;
  1452. X    t_mask  mask;
  1453. X    char   *np;
  1454. X
  1455. X    /* use `mask' to screen out most string comparisons */
  1456. X    mask = 0;
  1457. X    np = name;
  1458. X    while (*np)
  1459. X        mask += *np++;
  1460. X
  1461. X    /* linear search through symbol list */
  1462. X    for (symp = symbol_list; symp != NULL; symp = symp->snext)
  1463. X    {
  1464. X        if (mask != symp->smask)
  1465. X            continue;
  1466. X
  1467. X        if (equal(name, symp->sname))
  1468. X            return (symp);
  1469. X    }
  1470. X
  1471. X    symp = tnew(symnode);    /* allocate symbol node */
  1472. X    symp->smask = mask;    /* record mask for later */
  1473. X    symp->sname = tstrcpy(name);    /* allocate string and copy name */
  1474. X    symp->scmd = scmd;    /* command line macro? */
  1475. X    symp->slevel = make_level;    /* current new_make() level */
  1476. X
  1477. X    /* get the value from the environment, if it is there */
  1478. X
  1479. X    if ((symp->svalue = getenv(name)) != NULL)
  1480. X    {
  1481. X        symp->svalue = tstrcpy(symp->svalue);
  1482. X
  1483. X        /*
  1484. X         * if `-e', let command line macros override, but not macro
  1485. X         * assignments in the makefile. 
  1486. X         */
  1487. X        if (opts.envirn)
  1488. X            symp->scmd = 1;
  1489. X    }
  1490. X
  1491. X    symp->snext = symbol_list;    /* link to head of symbol list */
  1492. X    symbol_list = symp;
  1493. X
  1494. X    return (symp);
  1495. X}
  1496. X
  1497. X
  1498. X/*
  1499. X * dup_sym    - duplicate a symbol node, but at current new_make() level
  1500. X */
  1501. Xsymptr  dup_symbol(symp, value)
  1502. Xsymptr  symp;
  1503. Xchar   *value;
  1504. X{
  1505. X    symptr  nsp;
  1506. X
  1507. X    nsp = tnew(symnode);    /* allocate symbol node */
  1508. X    nsp->smask = symp->smask;    /* record mask for later */
  1509. X    nsp->sname = tstrcpy(symp->sname);    /* allocate string and copy
  1510. X                         * name */
  1511. X    nsp->svalue = (value == NULL) ? NULL : tstrcpy(value);
  1512. X    nsp->scmd = symp->scmd;    /* command line macro? */
  1513. X    nsp->slevel = make_level;    /* current new_make() level */
  1514. X
  1515. X    nsp->snext = symbol_list;    /* link to head of symbol list */
  1516. X    symbol_list = nsp;
  1517. X
  1518. X    return (nsp);
  1519. X}
  1520. X
  1521. X
  1522. X/*
  1523. X * add_target    - return extant target node, or create new one
  1524. X */
  1525. Xtargptr add_target(name)
  1526. Xchar   *name;
  1527. X{
  1528. X    t_mask  mask;
  1529. X    targptr targp;
  1530. X    fileptr filep;
  1531. X
  1532. X    /* each target must have a file node */
  1533. X    filep = add_file(name);
  1534. X
  1535. X    /* see if target already exists */
  1536. X    targp = hash_target(name, &mask);
  1537. X    if (targp)
  1538. X        return (targp);
  1539. X
  1540. X    /* oh well, gotta create one */
  1541. X    targp = tnew(targnode);    /* allocate a target node */
  1542. X    targp->tmask = mask;    /* save mask for later */
  1543. X    targp->tfile = filep;    /* save pointer to file node */
  1544. X    targp->tpreq = NULL;    /* no pre-req's yet */
  1545. X    targp->tshell = NULL;    /* no shell lines yet */
  1546. X
  1547. X    targp->tnext = target_list;    /* link to front of target list */
  1548. X    target_list = targp;
  1549. X
  1550. X    return (targp);
  1551. X}
  1552. X
  1553. X
  1554. X/*
  1555. X * hash_target    - look up target (by name) in target list
  1556. X *        - return target node or NULL
  1557. X *        - if requested, also return the mask
  1558. X */
  1559. Xtargptr hash_target(name, maskp)
  1560. Xchar   *name;
  1561. Xt_mask *maskp;
  1562. X{
  1563. X    targptr targp;
  1564. X    t_mask  mask;
  1565. X    char   *np;
  1566. X
  1567. X    /* use `mask' to screen out most string comparisons */
  1568. X    mask = 0;
  1569. X    np = name;
  1570. X    while (*np)
  1571. X        mask += *np++;
  1572. X
  1573. X    /* see if we gotta return it */
  1574. X    if (maskp != NULL)
  1575. X        *maskp = mask;
  1576. X
  1577. X    /* linear search through target list */
  1578. X    for (targp = target_list; targp != NULL; targp = targp->tnext)
  1579. X    {
  1580. X        if (mask != targp->tmask)
  1581. X            continue;
  1582. X
  1583. X        /* target name is ONLY stored in the file node */
  1584. X        if (equal(name, targp->tfile->fname))
  1585. X            return (targp);
  1586. X    }
  1587. X
  1588. X    /* nope, no target here */
  1589. X    return (NULL);
  1590. X}
  1591. X
  1592. X
  1593. X/*
  1594. X * add_file    - return a found or created file node
  1595. X */
  1596. Xfileptr add_file(name)
  1597. Xchar   *name;
  1598. X{
  1599. X    t_mask  mask;
  1600. X    fileptr filep;
  1601. X
  1602. X    /* see if file node already exists */
  1603. X    filep = hash_file(name, &mask);
  1604. X    if (filep)
  1605. X        return (filep);
  1606. X
  1607. X    filep = tnew(filenode);    /* allocate new file node */
  1608. X    filep->fmask = mask;    /* save mask for later */
  1609. X    filep->fname = tstrcpy(name);    /* allocate string and copy name */
  1610. X    filep->ftime = MAXNEGTIME;    /* init MODIFY time to long time ago */
  1611. X
  1612. X    filep->fnext = file_list;    /* link to head of file list */
  1613. X    file_list = filep;
  1614. X
  1615. X    return (filep);
  1616. X}
  1617. X
  1618. X
  1619. X/*
  1620. X * hash_file    - look up file (by name) in file list
  1621. X *        - return file node or NULL
  1622. X *        - if requested, also return the mask
  1623. X */
  1624. Xfileptr hash_file(name, maskp)
  1625. Xchar   *name;
  1626. Xt_mask *maskp;
  1627. X{
  1628. X    fileptr filep;
  1629. X    t_mask  mask;
  1630. X    char   *np;
  1631. X
  1632. X    /* use `mask' to screen out most string comparisons */
  1633. X    mask = 0;
  1634. X    np = name;
  1635. X    while (*np)
  1636. X        mask += *np++;
  1637. X
  1638. X    /* see if we gotta return it */
  1639. X    if (maskp != NULL)
  1640. X        *maskp = mask;
  1641. X
  1642. X    /* linear search through file list */
  1643. X    for (filep = file_list; filep != NULL; filep = filep->fnext)
  1644. X    {
  1645. X        if (filep->fmask != mask)
  1646. X            continue;
  1647. X
  1648. X        if (equal(filep->fname, name))
  1649. X            return (filep);
  1650. X    }
  1651. X
  1652. X    /* nope, no file here */
  1653. X    return (NULL);
  1654. X}
  1655. X
  1656. X
  1657. X/*
  1658. X * append_node    - add a node to the end of an array of nodes
  1659. X */
  1660. Xchar  **append_node(node, adds, size)
  1661. Xchar  **node;
  1662. Xchar  **adds;
  1663. Xint     size;
  1664. X{
  1665. X    int     addlen, len;
  1666. X
  1667. X    for (addlen = 0; adds[addlen] != NULL; ++addlen);
  1668. X    if (addlen++ == 0)
  1669. X        return (node);
  1670. X
  1671. X    len = 0;
  1672. X
  1673. X    if (node != NULL)
  1674. X    {
  1675. X        for (; node[len] != NULL; ++len);
  1676. X        node = (char **) trealloc((char *) node, (len + addlen) * size);
  1677. X    }
  1678. X    else
  1679. X        node = (char **) talloc(addlen * size);
  1680. X
  1681. X    memcpy(node + len, adds, addlen * size);
  1682. X    return (node);
  1683. X}
  1684. X
  1685. X/*
  1686. X * add_shell    - create a new shell node, and add to end of given list
  1687. X */
  1688. Xshellptr add_shell(input)
  1689. Xchar   *input;
  1690. X{
  1691. X    shellptr snode;
  1692. X
  1693. X    snode = tnew(shellnode);/* allocate a new shell node */
  1694. X    snode->s_shell = snode->s_ignore = snode->s_silent = 0;
  1695. X
  1696. X    for (; isspace(*input); ++input);    /* skip over leading spaces */
  1697. X    for (;; ++input)
  1698. X    {
  1699. X        if (*input == '+')
  1700. X            snode->s_shell = 1;    /* must use command.com */
  1701. X        else
  1702. X        if (*input == '-')
  1703. X            snode->s_ignore = 1;    /* ignore return value */
  1704. X        else
  1705. X        if (*input == '@')
  1706. X            snode->s_silent = 1;    /* don't echo command */
  1707. X        else
  1708. X            break;
  1709. X    }
  1710. X
  1711. X    snode->scmd = tstrcpy(input);    /* allocate string and copy command */
  1712. X
  1713. X    snode->slink = shell_list;    /* attach to global list */
  1714. X    shell_list = snode;
  1715. X
  1716. X    return (snode);
  1717. X}
  1718. X
  1719. X
  1720. X/*
  1721. X * breakout    - replace macro names with values
  1722. X *        - apply recursively
  1723. X * note: allocates (and returns) a string which must be freed
  1724. X */
  1725. Xchar   *breakout(input)
  1726. Xchar   *input;
  1727. X{
  1728. X    char   *dest, *dend;
  1729. X    char   *dp;
  1730. X    int     dlen;
  1731. X    int     tlen;
  1732. X    int     state;
  1733. X    char    symname[100];
  1734. X    char   *sp;
  1735. X    symptr  symp;
  1736. X    int     slen;
  1737. X    char    endch;
  1738. X
  1739. X    /* allocate a string twice as long as input string */
  1740. X
  1741. X    dlen = strlen(input) * 2;
  1742. X    dest = dp = talloc(dlen);
  1743. X    dend = dest + dlen;
  1744. X
  1745. X/*
  1746. X *     state machine with 4 states
  1747. X *        0)    normal text    -- just copy
  1748. X *        1)    starting macro    -- define end char (e.g. ')', '}')
  1749. X *        2)    macro name    -- copy to a buffer
  1750. X *        3)    end of macro    -- look up value, and copy
  1751. X */
  1752. X    state = 0;
  1753. X
  1754. X    while (*input || state == 3)
  1755. X    {
  1756. X        /* if we don't have enough room, double size of string */
  1757. X        if (dp == dend)
  1758. X        {
  1759. X            dlen *= 2;
  1760. X            tlen = dp - dest;
  1761. X            dest = trealloc(dest, dlen);
  1762. X            dp = dest + tlen;
  1763. X            dend = dest + dlen;
  1764. X        }
  1765. X
  1766. X        switch (state)
  1767. X        {
  1768. X        case 0:
  1769. X            if (*input == '$')
  1770. X                state = 1;    /* found a macro */
  1771. X            else
  1772. X                *dp++ = *input++;
  1773. X            break;
  1774. X
  1775. X        case 1:
  1776. X            state = 2;    /* only in this state for 1 char */
  1777. X            sp = symname;
  1778. X            switch (*++input)
  1779. X            {
  1780. X            case '$':
  1781. X                *dp++ = '$';
  1782. X                state = 0;
  1783. X                break;
  1784. X            case '(':
  1785. X                endch = ')';
  1786. X                break;
  1787. X            case '{':
  1788. X                endch = '}';
  1789. X                break;
  1790. X            default:
  1791. X                /* single char; go to state 3 immediately */
  1792. X                *sp++ = *input;
  1793. X                state = 3;
  1794. X                break;
  1795. X            }
  1796. X            ++input;/* skip bracket (or character) */
  1797. X            break;
  1798. X
  1799. X        case 2:
  1800. X            if (*input == endch)
  1801. X                state = 3;
  1802. X            else
  1803. X                *sp++ = *input;
  1804. X
  1805. X            if ((sp - symname) >= (sizeof symname / sizeof symname[0]))
  1806. X            {
  1807. X                sp[-1] = '\0';
  1808. X                terror(1,
  1809. X                tstrcat("Macro too long (limit 100 chars): ",
  1810. X                    symname));
  1811. X            }
  1812. X
  1813. X            ++input;/* make sure we skip end char */
  1814. X            break;
  1815. X
  1816. X        case 3:
  1817. X            *sp = '\0';
  1818. X            symp = get_symbol(symname, 0);
  1819. X            sp = symp->svalue;
  1820. X            slen = -1;
  1821. X            while (sp && *sp)
  1822. X            {
  1823. X                /*
  1824. X                 * if value has a macro in it, we must
  1825. X                 * process recursively 
  1826. X                 */
  1827. X                if (*sp == '$')
  1828. X                {
  1829. X                    sp = breakout(symp->svalue);
  1830. X                    /* now guaranteed not to have a '$' */
  1831. X                    slen = strlen(sp);
  1832. X                    break;
  1833. X                }
  1834. X                ++sp;
  1835. X            }
  1836. X
  1837. X            if (slen == -1)
  1838. X            {
  1839. X                /* value did NOT have a macro */
  1840. X                slen = (sp - symp->svalue);
  1841. X                sp = symp->svalue;
  1842. X            }
  1843. X
  1844. X            /* if we have not enough room, expand */
  1845. X            if (slen >= (dend - dp))
  1846. X            {
  1847. X                /* use slen to make sure that we can fit */
  1848. X                dlen = dlen * 2 + slen;
  1849. X                tlen = dp - dest;
  1850. X                dest = trealloc(dest, dlen);
  1851. X                dp = dest + tlen;
  1852. X                dend = dest + dlen;
  1853. X            }
  1854. X
  1855. X            /* if length is zero, don't bother to copy */
  1856. X            if (slen)
  1857. X            {
  1858. X                strcpy(dp, sp);
  1859. X                dp += slen;
  1860. X            }
  1861. X
  1862. X            if (sp != symp->svalue)
  1863. X                tfree(sp);    /* must've called `breakout' */
  1864. X
  1865. X            state = 0;    /* and we are back to text */
  1866. X            break;
  1867. X        }
  1868. X    }
  1869. X
  1870. X    if (state != 0)
  1871. X        terror(1, tstrcat("Improper macro.\n", dest));
  1872. X
  1873. X    *dp = '\0';        /* terminate the string */
  1874. X    return (dest);        /* and return it */
  1875. X}
  1876. END_OF_FILE
  1877. if test 17139 -ne `wc -c <'parse.c'`; then
  1878.     echo shar: \"'parse.c'\" unpacked with wrong size!
  1879. fi
  1880. # end of 'parse.c'
  1881. fi
  1882. if test -f 'tstring.c' -a "${1}" != "-c" ; then 
  1883.   echo shar: Will not clobber existing file \"'tstring.c'\"
  1884. else
  1885. echo shar: Extracting \"'tstring.c'\" \(5480 characters\)
  1886. sed "s/^X//" >'tstring.c' <<'END_OF_FILE'
  1887. X/*
  1888. X * tstring.c
  1889. X *
  1890. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  1891. X * 88-10-06 v1.1    changed prerequisite list handling
  1892. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  1893. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  1894. X * 89-08-01 v1.4 AB    lots of new options and code
  1895. X * 89-10-30 v1.5    -f -S -q options, took some changes from v1.4
  1896. X * 90-04-18 v1.6    -b -- -W options, emulate <<, non-BSD cleanup
  1897. X */
  1898. X#include <stdio.h>
  1899. X#include <ctype.h>
  1900. X#include <malloc.h>
  1901. X#include <string.h>
  1902. X
  1903. X#include "tstring.h"
  1904. X
  1905. X
  1906. Xchar   *talloc(n)
  1907. Xint     n;
  1908. X{
  1909. X    char   *s;
  1910. X
  1911. X    s = malloc(n);
  1912. X    if (s == NULL)
  1913. X        terror(1, "no free memory");
  1914. X    return (s);
  1915. X}
  1916. X
  1917. X
  1918. Xchar   *trealloc(s, n)
  1919. Xchar   *s;
  1920. Xint     n;
  1921. X{
  1922. X    s = realloc(s, n);
  1923. X    if (s == NULL)
  1924. X        talloc(n);    /* force an error */
  1925. X    return (s);
  1926. X}
  1927. X
  1928. X
  1929. Xchar   *tstrncpy(s, n)
  1930. Xchar   *s;
  1931. Xint     n;
  1932. X{
  1933. X    s = strncpy(talloc(n + 1), s, n);
  1934. X    s[n] = '\0';
  1935. X    return (s);
  1936. X}
  1937. X
  1938. X
  1939. Xterror(n, s)
  1940. Xint     n;
  1941. Xchar   *s;
  1942. X{
  1943. X    fputs("Make: ", stderr);
  1944. X    fputs(s, stderr);
  1945. X    putc('\n', stderr);
  1946. X    if (n)
  1947. X        exit(n);
  1948. X}
  1949. X
  1950. X
  1951. X/*
  1952. X * tstrspan -    move to the end of a quoted string, ignoring escaped quotes
  1953. X */
  1954. Xchar   *tstrspan(str)
  1955. Xchar   *str;
  1956. X{
  1957. X    char    quote;
  1958. X
  1959. X    if (*str != '\'' && *str != '"')
  1960. X        return (str + 1);
  1961. X
  1962. X    quote = *str++;
  1963. X
  1964. X    while (*str && *str != quote)
  1965. X    {
  1966. X        /* check for escaped quote */
  1967. X        if (*str == '\\' && str[1] == quote)
  1968. X            ++str;
  1969. X        ++str;
  1970. X    }
  1971. X
  1972. X    return (str);
  1973. X}
  1974. X
  1975. X
  1976. X/*
  1977. X * tunquote -    remove quotes from a string
  1978. X */
  1979. Xchar   *tunquote(str)
  1980. Xchar   *str;
  1981. X{
  1982. X    char   *s;
  1983. X    char   *d;
  1984. X
  1985. X    d = s = str;
  1986. X
  1987. X    while (*s)
  1988. X    {
  1989. X        while (*s && *s == '"')
  1990. X            ++s;
  1991. X
  1992. X        while (*s && *s != '"')
  1993. X            *d++ = *s++;
  1994. X    }
  1995. X
  1996. X    *d = '\0';
  1997. X
  1998. X    return (str);
  1999. X}
  2000. X
  2001. X
  2002. X/*
  2003. X * tsplit -    split a string into two components, normally a directory
  2004. X *        path and a filename.  If a pointer to a directory is
  2005. X *        supplied, a string is allocated to contain the directory.
  2006. X *        The filename is returned as a pointer into the supplied
  2007. X *        string.
  2008. X */
  2009. Xchar   *tsplit(s, seps, dp)
  2010. Xchar   *s;
  2011. Xchar   *seps;
  2012. Xchar  **dp;
  2013. X{
  2014. X    char   *d;        /* directory portion */
  2015. X    char   *f;        /* file portion */
  2016. X
  2017. X    d = s;
  2018. X
  2019. X    /* find the final separator */
  2020. X    while ((f = strpbrk(d, seps)) != NULL)
  2021. X        d = f + 1;
  2022. X
  2023. X    /* back up to final component */
  2024. X    f = d;
  2025. X
  2026. X    /* if we are still at the beginning, there was no Directory */
  2027. X    if (d == s || dp == NULL)
  2028. X        d = NULL;
  2029. X    else
  2030. X    {
  2031. X        int     len;
  2032. X
  2033. X        /*
  2034. X         * by the time we get here, d points to the final separator
  2035. X         * char.  we can substitute a NULL for this sep-char.  Thus,
  2036. X         * we don't need to add 1 in the following length
  2037. X         * calculation. 
  2038. X         */
  2039. X        len = d - s;
  2040. X
  2041. X        d = talloc(len);
  2042. X        d[--len] = '\0';
  2043. X        while (--len >= 0)
  2044. X            d[len] = s[len];
  2045. X    }
  2046. X
  2047. X    if (dp != NULL)
  2048. X        *dp = d;
  2049. X
  2050. X    return (f);
  2051. X}
  2052. X
  2053. X
  2054. X/*
  2055. X * token    - take an input string and return a token each call
  2056. X *        - default token delimiter characters are `isspace()'
  2057. X *        - separator chars are in addition to `isspace()'
  2058. X *        - text between quotes (" and ') is a single token
  2059. X *        - if requested, the separator char is returned
  2060. X *
  2061. X *    called as    s = token(string, seps, &schar);
  2062. X *        or    s = token(string, NULL, NULL);
  2063. X *
  2064. X *    followed by    s = token(NULL, seps, NULL);
  2065. X *        or    s = token(NULL, NULL, &schar);
  2066. X *
  2067. X *    returns NULL when no more tokens are available
  2068. X */
  2069. Xchar   *token(s, sep, schar)
  2070. Xchar   *s;
  2071. Xchar   *sep;
  2072. Xchar   *schar;
  2073. X{
  2074. X    static char *olds = NULL;
  2075. X
  2076. X    if (s)
  2077. X        olds = s;    /* we are starting all over again */
  2078. X
  2079. X    if (schar)
  2080. X        *schar = '\0';
  2081. X
  2082. X    if (!olds || !*olds)
  2083. X        return (NULL);    /* no tokens left */
  2084. X
  2085. X    while (isspace(*olds) || (sep && strchr(sep, *olds)))
  2086. X        ++olds;        /* skip leading spaces and sep's */
  2087. X
  2088. X    if (*olds == NULL)
  2089. X        return (NULL);    /* remainder is all separator's */
  2090. X
  2091. X    s = olds;
  2092. X
  2093. X    while (*olds)
  2094. X    {
  2095. X        if (isspace(*olds) || (sep && strchr(sep, *olds)))
  2096. X        {
  2097. X            if (schar)
  2098. X                *schar = *olds;
  2099. X            *olds++ = '\0';    /* delimit the token */
  2100. X            return (s);
  2101. X        }
  2102. X        else
  2103. X        if (*olds == '"' || *olds == '\'')
  2104. X        {
  2105. X            olds = tstrspan(olds);
  2106. X            if (*olds != '\0')
  2107. X                ++olds;    /* didn't hit eos, so skip quote */
  2108. X        }
  2109. X        else
  2110. X            ++olds;    /* otherwise, pass over char */
  2111. X    }
  2112. X
  2113. X    olds = NULL;
  2114. X    return (s);        /* return last token */
  2115. X}
  2116. X
  2117. X
  2118. X/*
  2119. X * tokenize    - chop a string up into an array of (char *)'s
  2120. X */
  2121. Xchar  **tokenize(input)
  2122. Xchar   *input;
  2123. X{
  2124. X    char  **argv;
  2125. X    int     argc = 0;
  2126. X    int     alen;
  2127. X
  2128. X    alen = 20;        /* good initial guess */
  2129. X    argv = (char **) talloc((alen + 1) * sizeof(char *));
  2130. X
  2131. X    input = token(input, NULL, NULL);    /* use default separators */
  2132. X    while (input)
  2133. X    {
  2134. X        if (alen == argc)
  2135. X            argv = (char **) trealloc((char *) argv,
  2136. X                         (alen <<= 1) * sizeof(char *));
  2137. X        argv[argc++] = input;
  2138. X        input = token(NULL, NULL, NULL);
  2139. X    }
  2140. X
  2141. X    argv[argc] = NULL;    /* mark end of array */
  2142. X
  2143. X    return (argv);
  2144. X}
  2145. X
  2146. X
  2147. X/*
  2148. X * tgets    - read input, swallowing escaped newlines as necessary
  2149. X */
  2150. Xchar   *tgets(fd)
  2151. XFILE   *fd;
  2152. X{
  2153. X    static char *input = NULL;
  2154. X    static int inlen = 0;
  2155. X    char   *ep;
  2156. X    int     len;
  2157. X
  2158. X    if (inlen == 0)
  2159. X        input = talloc(inlen = 162);
  2160. X
  2161. X    input[inlen - 2] = '\n';
  2162. X    ep = input - 1;
  2163. X    while ((fgets(input, inlen, fd)) != NULL)
  2164. X    {
  2165. X        for (;;)
  2166. X        {
  2167. X            while (input[inlen - 2] != '\n' && input[inlen - 2] != '\0')
  2168. X            {
  2169. X                len = inlen;
  2170. X                input = trealloc(input, inlen <<= 1);
  2171. X                ep = &input[len - 2];
  2172. X                input[inlen - 2] = '\n';
  2173. X                fgets(ep + 1, len + 1, fd);
  2174. X            }
  2175. X
  2176. X            while (*++ep);
  2177. X            *--ep = '\0';
  2178. X            do
  2179. X            {
  2180. X                --ep;
  2181. X            } while (ep >= input && isspace(*ep));
  2182. X
  2183. X            if (ep > input && *ep == '\\' && *--ep != '\\')
  2184. X                fgets(ep + 1, inlen - (ep - input) - 1, fd);
  2185. X            else
  2186. X                break;
  2187. X        }
  2188. X
  2189. X        return (input);
  2190. X    }
  2191. X
  2192. X    inlen = 0;
  2193. X    tfree(input);
  2194. X    input = NULL;
  2195. X
  2196. X    return (NULL);
  2197. X}
  2198. END_OF_FILE
  2199. if test 5480 -ne `wc -c <'tstring.c'`; then
  2200.     echo shar: \"'tstring.c'\" unpacked with wrong size!
  2201. fi
  2202. # end of 'tstring.c'
  2203. fi
  2204. if test -f 'tstring.h' -a "${1}" != "-c" ; then 
  2205.   echo shar: Will not clobber existing file \"'tstring.h'\"
  2206. else
  2207. echo shar: Extracting \"'tstring.h'\" \(1310 characters\)
  2208. sed "s/^X//" >'tstring.h' <<'END_OF_FILE'
  2209. X/*
  2210. X * tstring.h
  2211. X *
  2212. X * 88-10-01 v1.0    created by greg yachuk, placed in the public domain
  2213. X * 88-10-06 v1.1    changed prerequisite list handling
  2214. X * 88-11-11 v1.2    fixed some bugs and added environment variables
  2215. X * 89-07-12 v1.3    stop appending shell commands, and flush output
  2216. X * 89-08-01 v1.4 AB    lots of new options and code
  2217. X * 89-10-30 v1.5    -f -S -q options, took some changes from v1.4
  2218. X * 90-04-18 v1.6    -b -- -W options, emulate <<, non-BSD cleanup
  2219. X */
  2220. X#define    tnew(t)        ((t *) talloc(sizeof(t)))
  2221. X#define    tfree(t)    (free((char *) t))
  2222. X
  2223. X#define    tstrcat(s,p)    (strcat(strcpy(talloc(strlen(s)+strlen(p)+1),(s)),(p)))
  2224. X#define    tstrcpy(s)    (strcpy(talloc(strlen(s)+1), (s)))
  2225. X
  2226. X#ifdef    __STDC__
  2227. Xextern char *talloc(int n);
  2228. Xextern char *trealloc(char *s, int n);
  2229. Xextern char *tstrncpy(char *s, int n);
  2230. Xextern int terror(int n, char *s);
  2231. Xextern char *tstrspan(char *str);
  2232. Xextern char *tunquote(char *str);
  2233. Xextern char *tsplit(char *s, char *seps, char **dp);
  2234. Xextern char *token(char *s, char *sep, char *schar);
  2235. Xextern char **tokenize(char *input);
  2236. Xextern char *tgets(FILE * fd);
  2237. X#else
  2238. Xextern char *talloc();
  2239. Xextern char *trealloc();
  2240. Xextern char *tstrncpy();
  2241. Xextern int terror();
  2242. Xextern char *tstrspan();
  2243. Xextern char *tunquote();
  2244. Xextern char *tsplit();
  2245. Xextern char *token();
  2246. Xextern char **tokenize();
  2247. Xextern char *tgets();
  2248. X#endif
  2249. END_OF_FILE
  2250. if test 1310 -ne `wc -c <'tstring.h'`; then
  2251.     echo shar: \"'tstring.h'\" unpacked with wrong size!
  2252. fi
  2253. # end of 'tstring.h'
  2254. fi
  2255. echo shar: End of archive 2 \(of 2\).
  2256. cp /dev/null ark2isdone
  2257. MISSING=""
  2258. for I in 1 2 ; do
  2259.     if test ! -f ark${I}isdone ; then
  2260.     MISSING="${MISSING} ${I}"
  2261.     fi
  2262. done
  2263. if test "${MISSING}" = "" ; then
  2264.     echo You have unpacked both archives.
  2265.     rm -f ark[1-9]isdone
  2266. else
  2267.     echo You still need to unpack the following archives:
  2268.     echo "        " ${MISSING}
  2269. fi
  2270. ##  End of shell archive.
  2271. exit 0
  2272.  
  2273.